﻿using FreeSql;
using Kernel.Core.IService;
using Kernel.Core.Models.Cache;
using Kernel.Core.Models.Settings;
using Kernel.Core.Service;
using Kernel.IService.Repository.Demo;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption;
using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel;
using Swashbuckle.AspNetCore.SwaggerGen;
using System.Data.SQLite;
using WebAPI.Configure.AuthHandler;

namespace WebAPI.Configure;

public static class ServiceCollectionExtensions
{
    public static void RegisterServices(this IServiceCollection services, IConfiguration configuration)
    {
        //var provider = services.BuildServiceProvider();
        //var DapperFactory = provider.GetService<IDapperFactory>();

        //注册Repository
        //services.AddScoped<IUserRepository>((iServiceProvider) => DapperFactory.CreateRepository<UserRepository>(DapperConst.QYPT_ORACLE));

        //自定义授权策略
        services.AddSingleton<IAuthorizationHandler, MinimumAgeHandler>();

        var fsql1 = new FreeSqlBuilder().UseConnectionFactory(FreeSql.DataType.Sqlite, () =>
        {
            var conn = new SQLiteConnection(string.Format(configuration.GetSection("DBConnction:SqliteConnection").Value, Config.SettingFolder));
            var connection = new StackExchange.Profiling.Data.ProfiledDbConnection(conn, MiniProfiler.Current);
            return connection;
        }).UseAutoSyncStructure(true).Build<KernelSqliteFlag>();

        services.AddSingleton<IFreeSql<KernelSqliteFlag>>(fsql1);

        var fsql2 = new FreeSqlBuilder().UseConnectionString(FreeSql.DataType.MySql, configuration.GetSection("DBConnction:MySQLConnection").Value)
            .UseMonitorCommand(cmd =>//执行前
            {
                Console.WriteLine("--------------------------------------------------执行前begin--------------------------------------------------");
                Console.WriteLine(cmd.CommandText);
                Console.WriteLine("--------------------------------------------------执行前end--------------------------------------------------");
            }, (cmd, valueString) =>//执行后
            {
                Console.WriteLine("--------------------------------------------------执行后begin--------------------------------------------------");
                Console.WriteLine(cmd.CommandText);
                Console.WriteLine(valueString);
                Console.WriteLine("--------------------------------------------------执行后end--------------------------------------------------");
            })
            .UseAutoSyncStructure(true).Build<MySqlFlag>();

        services.AddSingleton<IFreeSql<MySqlFlag>>(fsql2);

        //注入缓存服务
        services.AddSingleton<ICacheService<KernelCacheFlag>>((IServiceProvider isp) =>
        {
            var fsql = isp.GetService<IFreeSql<KernelSqliteFlag>>();
            var repo = fsql.GetRepository<SqliteDBCache>();
            return new DBCacheService<KernelCacheFlag, SqliteDBCache>(repo);
        });

        //DataProtection
        services.AddDataProtection()
          //可以传入一个共享文件夹，来存储私钥，这样在不同机器的私钥就可以保存到一个位置了。可以通过此种方式在分布式部署的时候，隔离开了机器的差异化
          .PersistKeysToFileSystem(new DirectoryInfo(Config.SettingFolder + "/PersistKeys"))
          //如果你觉得不安全，还可以配置一个X.509证书来，进行加密，thumbprint就是证书的指纹（去掉空格，不区分大小写）
          //.ProtectKeysWithCertificate("thumbprint")
          //Data Protection 的默认保存时间是90天，你可以通过以下方式来修改默认的保存时间
          .SetDefaultKeyLifetime(TimeSpan.FromDays(180))
          //默认情况下，即使使用相同的物理密钥库，Data Protection 也会把不同的应用程序隔离开，因为这样可以防止从一个应用程序获取另外一个应用程序的密钥。所以如果是相同的应用程序，可以设置相同的应用程序名称，用于分布式布署
          .SetApplicationName(Env.Current.KERNEL_SERVICE_NAME)
          //有时候需要禁用应用程序生成密钥，或者是说我只有一个程序用来生成或者管理密钥，其他程序只是负责读的话，那么可以这样
          //.DisableAutomaticKeyGeneration()
          //修改加密算法
          .UseCryptographicAlgorithms(new AuthenticatedEncryptorConfiguration()
          {
              EncryptionAlgorithm = EncryptionAlgorithm.AES_256_CBC,
              ValidationAlgorithm = ValidationAlgorithm.HMACSHA256
          });

        //添加swagger配置
        services.AddTransient<IConfigureOptions<SwaggerGenOptions>, ConfigureSwaggerOptions>();

        //初始化后，RedisHelper工具类才能正常使用
        RedisHelper.Initialization(new CSRedis.CSRedisClient("127.0.0.1:6379,password=123,defaultDatabase=13,poolsize=50,connectTimeout=200,ssl=false,writeBuffer=10240,prefix=key前辍"));

    }

}
